import 'package:flutter/material.dart';

/*

 GridView可以构建一个二维网格列表，其默认构造函数定义如下：
 
 GridView({
   Axis scrollDirection = Axis.vertical,
   bool reverse = false,
   ScrollController controller,
   bool primary,
   ScrollPhysics physics,
   bool shrinkWrap = false,
   EdgeInsetsGeometry padding,
   @required SliverGridDelegate gridDelegate, //控制子widget layout的委托
   bool addAutomaticKeepAlives = true,
   bool addRepaintBoundaries = true,
   double cacheExtent,
   List<Widget> children = const <Widget>[],
 })
 我们可以看到，GridView和ListView的大多数参数都是相同的，它们的含义也都相同的，如有疑惑读者可以翻阅ListView一节，
 在此不再赘述。我们唯一需要关注的是gridDelegate参数，类型是SliverGridDelegate，它的作用是控制GridView子组件如
 何排列(layout)。
 
 SliverGridDelegate是一个抽象类，定义了GridView Layout相关接口，子类需要通过实现它们来实现具体的布局算法。
 Flutter中提供了两个SliverGridDelegate的子类SliverGridDelegateWithFixedCrossAxisCount和
 SliverGridDelegateWithMaxCrossAxisExtent，我们可以直接使用，下面我们分别来介绍一下它们。

 */

class GridViewPage1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Grid View 1"),
      ),
      body: Flex(
        direction: Axis.vertical,
        children: <Widget>[

          ///
          /// SliverGridDelegateWithFixedCrossAxisCount
          ///  
          /// 该子类实现了一个横轴为固定数量子元素的layout算法，其构造函数为：
          /// 
          /// SliverGridDelegateWithFixedCrossAxisCount({
          ///   @required double crossAxisCount, 
          ///   double mainAxisSpacing = 0.0,
          ///   double crossAxisSpacing = 0.0,
          ///   double childAspectRatio = 1.0,
          /// })
          /// 
          /// - crossAxisCount：横轴子元素的数量。此属性值确定后子元素在横轴的长度就确定了，即ViewPort横轴长度除以crossAxisCount的商。
          /// - mainAxisSpacing：主轴方向的间距。
          /// - crossAxisSpacing：横轴方向子元素的间距。
          /// - childAspectRatio：子元素在横轴长度和主轴长度的比例。由于crossAxisCount指定后，子元素横轴长度就确定了，然后通过此参数值
          ///    就可以确定子元素在主轴的长度。
          /// 
          /// 可以发现，子元素的大小是通过crossAxisCount和childAspectRatio两个参数共同决定的。注意，这里的子元素指的是子组件的最大显
          /// 示空间，注意确保子组件的实际大小不要超出子元素的空间。
          /// 
          Expanded(
            flex: 1,
            child: Container(
              color: Colors.red,
              child: GridView(
                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 3,  // 横轴3个子widget
                  childAspectRatio: 1.0 // 宽高比为1
                ),
                children: <Widget>[
                  Icon(Icons.ac_unit),
                  Icon(Icons.airport_shuttle),
                  Icon(Icons.all_inclusive),
                  Icon(Icons.beach_access),
                  Icon(Icons.cake),
                  Icon(Icons.free_breakfast)
                ],
              ),
            ),
          ),

          /// GridView.count构造函数内部使用了SliverGridDelegateWithFixedCrossAxisCount
          Expanded(
            flex: 1,
            child: Container(
              color: Colors.blue,
              child: GridView.count(
                crossAxisCount: 3,
                childAspectRatio: 1,
                children: <Widget>[
                  Icon(Icons.ac_unit),
                  Icon(Icons.airport_shuttle),
                  Icon(Icons.all_inclusive),
                  Icon(Icons.beach_access),
                  Icon(Icons.cake),
                  Icon(Icons.free_breakfast)
                ],
              ),
            ),
          ),

          ///
          /// SliverGridDelegateWithMaxCrossAxisExtent
          /// 
          /// 该子类实现了一个横轴子元素为固定最大长度的layout算法，其构造函数为：
          /// 
          /// SliverGridDelegateWithMaxCrossAxisExtent({
          ///   double maxCrossAxisExtent,
          ///   double mainAxisSpacing = 0.0,
          ///   double crossAxisSpacing = 0.0,
          ///   double childAspectRatio = 1.0,
          /// })
          /// maxCrossAxisExtent为子元素在横轴上的最大长度，之所以是“最大”长度，是因为横轴方向每个子元素的
          /// 长度仍然是等分的，举个例子，如果ViewPort的横轴长度是450，那么当maxCrossAxisExtent的值在区
          /// 间[450/4，450/3)内的话，子元素最终实际长度都为112.5，而childAspectRatio所指的子元素横轴和
          /// 主轴的长度比为最终的长度比。其它参数和SliverGridDelegateWithFixedCrossAxisCount相同。
          /// 
          Expanded(
            flex: 1,
            child: Container(
              color: Colors.yellow,
              child: GridView(
                padding: EdgeInsets.all(10),
                gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
                  maxCrossAxisExtent: 120,
                  childAspectRatio: 2.0
                ),
                children: <Widget>[
                  Icon(Icons.ac_unit),
                  Icon(Icons.airport_shuttle),
                  Icon(Icons.all_inclusive),
                  Icon(Icons.beach_access),
                  Icon(Icons.cake),
                  Icon(Icons.free_breakfast)
                ],
              ),
            ),
          ),

          /// GridView.extent构造函数内部使用了SliverGridDelegateWithMaxCrossAxisExtent
          Expanded(
            flex: 1,
            child: Container(
              color: Colors.cyan,
              child: GridView.extent(
                maxCrossAxisExtent: 120.0,
                childAspectRatio: 2.0,
                children: <Widget>[
                  Icon(Icons.ac_unit),
                  Icon(Icons.airport_shuttle),
                  Icon(Icons.all_inclusive),
                  Icon(Icons.beach_access),
                  Icon(Icons.cake),
                  Icon(Icons.free_breakfast)
                ],
              ),
            ),
          )
        ],
      )
    );
  }
}